#include <stdio.h>
#include <stdlib.h>

#include "MQTTClient.h"
#include "cJSON.h"
#include "cmsis_os2.h"
#include "config_network.h"
#include "iot.h"
#include "los_task.h"
#include "ohos_init.h"

#define REQUEST_ID_LENG 36                                  // 回复request_id长度36
#define HOST_ADDR "123.60.221.196"                          // Iot平台hostname

#define CLIENT_ID "smartGarageTX_0_0_2025041814"            // Iot平台ClientId
#define MQTT_DEVICES_USRNM "dev_user"                       // Iot平台MQTT_DEVICES_USTNM
#define MQTT_DEVICES_PWD "Aa123456"                         // Iot平台Password
#define APP_DEV_ID "OH_Simulator_0_0_2025041814"

#define PUBLISH_TOPIC "$oc/devices/" MQTT_DEVICES_USRNM "/sys/properties/report"
#define SUBCRIB_TOPIC "$oc/devices/" MQTT_DEVICES_USRNM "/sys/commands/#"           // request_id={request_id}"
#define RESPONSE_TOPIC "$oc/devices/" MQTT_DEVICES_USRNM "/sys/commands/response"   // request_id={request_id}"
#define SUBSCRIB_TOPIC_APP_EVENT "$oc/devices/" MQTT_DEVICES_USRNM "/sys/events/#"

#define MAX_BUFFER_LENGTH 512
#define MAX_STRING_LENGTH 64

static unsigned char sendBuf[MAX_BUFFER_LENGTH];
static unsigned char readBuf[MAX_BUFFER_LENGTH];

Network network;
MQTTClient client;

static unsigned int mqttConnectFlag = 0;

extern bool light_state;
extern bool auto_state;

/***************************************************************
 * 函数名称: send_msg_to_mqtt
 * 说  明: 发送信息到iot
 * 参  数: e_iot_data *iot_data：数据
 * 返 回 值: 无
 ***************************************************************/
void send_msg_to_mqtt(e_iot_data *iot_data)
{
  int rc;
  MQTTMessage message;
  char *publishtopic = PUBLISH_TOPIC;
  char payload[MAX_BUFFER_LENGTH] = {0};
  char str[MAX_STRING_LENGTH] = {0};

  if (mqttConnectFlag == 0)
  {
    printf("mqtt not connect\n");
    return;
  }

  cJSON *root = cJSON_CreateObject();
  if (root != NULL)
  {
    cJSON *serv_arr = cJSON_AddArrayToObject(root, "services");
    cJSON *arr_item = cJSON_CreateObject();
    cJSON_AddStringToObject(arr_item, "service_id", "smartGarage");
    cJSON *pro_obj = cJSON_CreateObject();
    cJSON_AddItemToObject(arr_item, "properties", pro_obj);

    memset(str, 0, MAX_BUFFER_LENGTH);

    // 人体状态
    if (iot_data->human_state == true)
    {
      cJSON_AddStringToObject(pro_obj, "humanStatus", "ON");
    }
    else
    {
      cJSON_AddStringToObject(pro_obj, "humanStatus", "OFF");
    }

    // 灯光状态
    if (iot_data->light_state == true)
    {
      cJSON_AddStringToObject(pro_obj, "lightStatus", "ON");
    }
    else
    {
      cJSON_AddStringToObject(pro_obj, "lightStatus", "OFF");
    }

    // 自动状态模式
    if (iot_data->auto_state == true)
    {
      cJSON_AddStringToObject(pro_obj, "autoStatus", "ON");
    }
    else
    {
      cJSON_AddStringToObject(pro_obj, "autoStatus", "OFF");
    }

    cJSON_AddItemToArray(serv_arr, arr_item);

    char *palyload_str = cJSON_PrintUnformatted(root);
    strcpy(payload, palyload_str);

    cJSON_free(palyload_str);
    cJSON_Delete(root);
  }

  message.qos = 0;
  message.retained = 0;
  message.payload = payload;
  message.payloadlen = strlen(payload);

  if ((rc = MQTTPublish(&client, publishtopic, &message)) != 0)
  {
    printf("Return code from MQTT publish is %d\n", rc);
    mqttConnectFlag = 0;
  }
  else
  {
    printf("mqtt publish success:%s\n", payload);
  }
}
/***************************************************************
 * 函数名称: set_light_state
 * 说  明: 设置灯状态
 * 参  数: cJSON *root
 * 返 回 值: 无
 ***************************************************************/
void set_light_state(cJSON *root)
{
  cJSON *para_obj = NULL;
  cJSON *status_obj = NULL;
  char *value = NULL;

  para_obj = cJSON_GetObjectItem(root, "paras");
  status_obj = cJSON_GetObjectItem(para_obj, "onoff");
  if (status_obj != NULL)
  {
    value = cJSON_GetStringValue(status_obj);
    if (!strcmp(value, "ON"))
    {
      light_state = true;
      auto_state = false;   // 关闭自动模式
    }
    else if (!strcmp(value, "OFF"))
    {
      light_state = false;
      auto_state = false;   // 关闭自动模式
    }
    else
    {
      printf("light state parse failed. value = %s\n", value);
    }
  }
  else
  {
    printf("light state parse failed. status_obj = NULL\n");
  }
}

/***************************************************************
 * 函数名称: set_auto_state
 * 说  明: 设置自动模式状态
 * 参  数: cJSON *root
 * 返 回 值: 无
 ***************************************************************/
void set_auto_state(cJSON *root)
{
  cJSON *para_obj = NULL;
  cJSON *status_obj = NULL;
  char *value = NULL;

  para_obj = cJSON_GetObjectItem(root, "paras");
  status_obj = cJSON_GetObjectItem(para_obj, "onoff");
  if (status_obj != NULL)
  {
    value = cJSON_GetStringValue(status_obj);
    if (!strcmp(value, "ON"))
    {
      auto_state = true;
    }
    else if (!strcmp(value, "OFF"))
    {
      auto_state = false;
    }
    else
    {
      printf("auto state parse failed. value = %s\n", value);
    }
  }
  else
  {
    printf("auto state parse failed. status_obj = NULL\n");
  }
}

/***************************************************************
 * 函数名称: mqtt_message_arrived
 * 说  明: 接收mqtt数据
 * 参  数: MessageData *data
 * 返 回 值: 无
 ***************************************************************/
void mqtt_message_arrived(MessageData *data)
{
  int rc;
  cJSON *root = NULL;
  cJSON *cmd_name = NULL;
  char *cmd_name_str = NULL;
  char *request_id_idx = NULL;
  char request_id[REQUEST_ID_LENG] = {0};
  MQTTMessage message;
  char payload[MAX_BUFFER_LENGTH];
  char rsptopic[254] = {0};

  printf("Message arrived on topic %.*s: %.*s\n",
         data->topicName->lenstring.len, data->topicName->lenstring.data,
         data->message->payloadlen, data->message->payload);

  root = cJSON_ParseWithLength(data->message->payload, data->message->payloadlen);
  if (root != NULL)
  {
    cmd_name = cJSON_GetObjectItem(root, "command_name");
    if (cmd_name != NULL)
    {
      cmd_name_str = cJSON_GetStringValue(cmd_name);
      if (!strcmp(cmd_name_str, "light_control"))
      {
        set_light_state(root);
      }
      else if (!strcmp(cmd_name_str, "auto_control"))
      {
        set_auto_state(root);
      }
      else{
        printf("command parse failed. cmd_name_str = %s\n", cmd_name_str);
      }
    }
    else
    {
      printf("command parse failed. cmd_name = NULL\n");
    }
  }
  else
  {
    printf("command parse failed. root = NULL\n");
  }

  cJSON_Delete(root);
}

/***************************************************************
 * 函数名称: wait_message
 * 说  明: 等待信息
 * 参  数: 无
 * 返 回 值: 无
 ***************************************************************/
int wait_message()
{
  uint8_t rec = MQTTYield(&client, 5000);
  if (rec != 0)
  {
    mqttConnectFlag = 0;
  }
  if (mqttConnectFlag == 0)
  {
    return 0;
  }
  return 1;
}

/***************************************************************
 * 函数名称: mqtt_init
 * 说  明: mqtt初始化
 * 参  数: 无
 * 返 回 值: 无
 ***************************************************************/
void mqtt_init()
{
  int rc;

  printf("Starting MQTT...\n");
  /*网络初始化*/
  NetworkInit(&network);

begin:
  /* 连接网络*/
  printf("NetworkConnect ...\n");
  NetworkConnect(&network, HOST_ADDR, 1883);
  printf("MQTTClientInit ...\n");
  /*MQTT客户端初始化*/
  MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf,
                 sizeof(readBuf));

  MQTTString clientId = MQTTString_initializer;
  clientId.cstring = CLIENT_ID;

  MQTTString username = MQTTString_initializer;
  username.cstring = MQTT_DEVICES_USRNM;

  MQTTString password = MQTTString_initializer;
  password.cstring = MQTT_DEVICES_PWD;

  MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
  data.clientID = clientId;
  data.username = username;
  data.password = password;
  data.willFlag = 0;
  data.MQTTVersion = 4;
  data.keepAliveInterval = 60;
  data.cleansession = 1;

  printf("MQTTConnect ...\n");
  rc = MQTTConnect(&client, &data);
  if (rc != 0)
  {
    printf("MQTTConnect: %d\n", rc);
    NetworkDisconnect(&network);
    MQTTDisconnect(&client);
    osDelay(200);
    goto begin;
  }

  printf("MQTTSubscribe ...\n");
  rc = MQTTSubscribe(&client, SUBCRIB_TOPIC, 0, mqtt_message_arrived);
  osDelay(200);
  rc |= MQTTSubscribe(&client, SUBSCRIB_TOPIC_APP_EVENT, 0, mqtt_message_arrived);
  if (rc != 0)
  {
    printf("MQTTSubscribe: %d\n", rc);
    osDelay(200);
    goto begin;
  }

  mqttConnectFlag = 1;
}

/***************************************************************
 * 函数名称: mqtt_is_connected
 * 说  明: mqtt连接状态
 * 参  数: 无
 * 返 回 值: unsigned int 状态
 ***************************************************************/
unsigned int mqtt_is_connected()
{
  return mqttConnectFlag;
}
